package com.hhkj.admin.train.common.component.supplier;

import cn.hutool.core.collection.CollectionUtil;
import com.hhkj.admin.student.domain.StudentCourseTrainCount;
import com.hhkj.admin.student.model.dopo.StudentLoginTimesCountPo;
import com.hhkj.admin.student.service.base.StudentLoginLogService;
import com.hhkj.admin.train.model.dopo.TrainCountPo;
import com.hhkj.admin.train.model.dopo.TrainPo;
import com.hhkj.admin.train.service.base.TrainService;
import com.hhkj.api.train.common.cont.ApiTrainConst;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MathUtils;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * TrainCountSupplier
 *
 * @author HHKJ-SERVER-ZJ
 * @since 2023/10/11 11:40
 */
@Component
public class TrainCountSupplier {

    @Autowired
    private StudentLoginLogService loginLogService;
    @Autowired
    private TrainService trainService;

    private final String DEFAULT_DURATION_TIME = "0分0秒";

    /**
     * 补充学员考试详情
     *
     * @param trainCountList 培训统计列表
     * @param studentIdList  学员id列表
     * @param courseIdList   课程id列表
     */
    public void supplyTrainDetail(List<StudentCourseTrainCount> trainCountList, List<Long> studentIdList, List<Long> courseIdList) {
        // 获取培训信息列表
        List<TrainPo> trainPoList = trainService.listByStudentIdListAndCourseIdList(studentIdList, courseIdList);
        Map<Long, Map<Long, Map<String, List<TrainPo>>>> trainPoListByTypeCodeAndCourseIdAndStudentIdMap
                = trainPoList.stream()
                .collect(Collectors.groupingBy(TrainPo::getStudentId,
                        Collectors.groupingBy(TrainPo::getCourseId,
                                Collectors.groupingBy(TrainPo::getTypeCode))));

        Map<Long, Map<String, List<TrainPo>>> trainPoListByTypeCodeAndCourseIdMap;
        Map<String, List<TrainPo>> trainPoListByTypeCodeMap;
        // 进行分组处理信息
        for (StudentCourseTrainCount trainCount : trainCountList) {
            if (trainPoListByTypeCodeAndCourseIdAndStudentIdMap.containsKey(trainCount.getStudentId())) {
                trainPoListByTypeCodeAndCourseIdMap
                        = trainPoListByTypeCodeAndCourseIdAndStudentIdMap.get(trainCount.getStudentId());
                if (trainPoListByTypeCodeAndCourseIdMap.containsKey(trainCount.getCourseId())) {
                    trainPoListByTypeCodeMap = trainPoListByTypeCodeAndCourseIdMap.get(trainCount.getCourseId());
                    if (trainPoListByTypeCodeMap.containsKey(ApiTrainConst.TypeCode.PRACTISE.getCode())) {
                        this.supplyPractiseDetail(trainCount, trainPoListByTypeCodeMap.get(ApiTrainConst.TypeCode.PRACTISE.getCode()));
                    }
                    if (trainPoListByTypeCodeMap.containsKey(ApiTrainConst.TypeCode.TEST.getCode())) {
                        this.supplyTestDetail(trainCount, trainPoListByTypeCodeMap.get(ApiTrainConst.TypeCode.TEST.getCode()));
                    }
                }
            }
        }
    }

    /**
     * 补充培训测试详情
     *
     * @param trainCount  培训信息
     * @param trainPoList 培训列表
     */
    private void supplyTestDetail(StudentCourseTrainCount trainCount, List<TrainPo> trainPoList) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        StringBuilder detail = new StringBuilder();
        detail.append("模拟测试：");
        for (TrainPo trainPo : trainPoList) {
            String costTime = DateUtils.getFormatDate(trainPo.getDurationSecond());
//            String info = StringUtils.format("{} {}分 用时{}", df.format(trainPo.getSubmitTime()), trainPo.getMark(), costTime);
//            detail.append(info).append("\n");
            //12.08 改为 “模拟测试：79，89，78，99” 这个样子
            detail.append(trainPo.getMark()).append("，");
        }
        detail.deleteCharAt(detail.length() - 1);
        trainCount.setTestInfoList(detail.toString());
    }

    /**
     * 补充培训练习详情
     *
     * @param trainCount  培训信息
     * @param trainPoList 培训列表
     */
    private void supplyPractiseDetail(StudentCourseTrainCount trainCount, List<TrainPo> trainPoList) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        StringBuilder detail = new StringBuilder();
        for (TrainPo trainPo : trainPoList) {
            String rightRate = MathUtils.calculateThePercentage(trainPo.getRightAmount(), trainPo.getAnswerAmount());
            String costTime = DateUtils.getFormatDate(trainPo.getDurationSecond());
            String info = StringUtils.format("{} 共练习{}题 正确率{} 用时{}", df.format(trainPo.getSubmitTime()), trainPo.getAnswerAmount(), rightRate, costTime);
            detail.append(info).append("\n");
        }
        trainCount.setPracticeInfoList(detail.toString());
    }

    /**
     * 补充学员最近测试
     *
     * @param trainCountList 培训统计列表
     * @param studentIdList  学员id列表
     * @param courseIdList   课程id列表
     */
    public void supplyLastTest(List<StudentCourseTrainCount> trainCountList, List<Long> studentIdList, List<Long> courseIdList) {
        if (CollectionUtil.isEmpty(trainCountList)) {
            return;
        }
        // 获取最近练习情况
        List<TrainPo> lastTrainPoList = trainService.listLastTrainByStudentIdListAndCourseIdList(studentIdList, courseIdList);

        Map<Long, Map<Long, Map<String, TrainPo>>> lastTrainPoByTypeCodeAndCourseIdAndStudentIdMap = lastTrainPoList.stream()
                .collect(Collectors.groupingBy(TrainPo::getStudentId,
                        Collectors.groupingBy(TrainPo::getCourseId,
                                Collectors.groupingBy(TrainPo::getTypeCode,
                                        Collectors.collectingAndThen(Collectors.toList(), CollectionUtil::getFirst)))));

        for (StudentCourseTrainCount trainCount : trainCountList) {
            this.supplyLastTest(trainCount, lastTrainPoByTypeCodeAndCourseIdAndStudentIdMap);
        }
    }

    /**
     * 补充学员练习统计
     *
     * @param trainCountList 培训统计列表
     * @param studentIdList  学员id列表
     * @param courseIdList   课程id列表
     */
    public void supplyPractiseCount(List<StudentCourseTrainCount> trainCountList, List<Long> studentIdList, List<Long> courseIdList) {
        if (CollectionUtil.isEmpty(trainCountList)) {
            return;
        }
        //查询练习情况
        List<TrainCountPo> trainCountPoList = trainService.listCountByStudentIdListAndCourseIdList(studentIdList, courseIdList);

        Map<Long, Map<Long, Map<String, TrainCountPo>>> trainCountByTypeCodeAndCourseIdAndStudentIdMap = trainCountPoList.stream()
                .collect(Collectors.groupingBy(TrainCountPo::getStudentId,
                        Collectors.groupingBy(TrainCountPo::getCourseId,
                                Collectors.groupingBy(TrainCountPo::getTypeCode,
                                        Collectors.collectingAndThen(Collectors.toList(), CollectionUtil::getFirst)))));

        for (StudentCourseTrainCount trainCount : trainCountList) {
            this.supplyPractiseCount(trainCount, trainCountByTypeCodeAndCourseIdAndStudentIdMap);
        }
    }

    /**
     * 补充学生登录信息
     *
     * @param trainCountList 培训统计列表
     * @param studentIdList  学员id列表
     */
    public void supplyLoginInfo(List<StudentCourseTrainCount> trainCountList, List<Long> studentIdList) {

        if (CollectionUtil.isEmpty(trainCountList)) {
            return;
        }

        //查询登录情况
        List<StudentLoginTimesCountPo> studentLoginCountPoList
                = loginLogService.listCountLoginByStudentIdListAndCourseIdList(studentIdList);

        Map<Long, Map<Long, StudentLoginTimesCountPo>> loginTimesByCourseIdAndStudentIdMap = studentLoginCountPoList.stream()
                .collect(Collectors.groupingBy(StudentLoginTimesCountPo::getStudentId,
                        Collectors.groupingBy(StudentLoginTimesCountPo::getCourseId,
                                Collectors.collectingAndThen(Collectors.toList(), CollectionUtil::getFirst))));

        for (StudentCourseTrainCount trainCount : trainCountList) {
            //关联登录次数、最近登录时间
            this.supplyLoginInfo(trainCount, loginTimesByCourseIdAndStudentIdMap);
        }
    }

    /**
     * 补充培训最新测试培训信息
     *
     * @param trainCount                                      统计信息
     * @param lastTrainPoByTypeCodeAndCourseIdAndStudentIdMap 最近练习信息
     */
    private void supplyLastTest(StudentCourseTrainCount trainCount, Map<Long, Map<Long, Map<String, TrainPo>>> lastTrainPoByTypeCodeAndCourseIdAndStudentIdMap) {
        BigDecimal mark = BigDecimal.ZERO;
        String durationTime = DEFAULT_DURATION_TIME;
        if (CollectionUtil.isNotEmpty(lastTrainPoByTypeCodeAndCourseIdAndStudentIdMap)
                && lastTrainPoByTypeCodeAndCourseIdAndStudentIdMap.containsKey(trainCount.getStudentId())) {
            Map<Long, Map<String, TrainPo>> lastTrainPoByTypeCodeAndCourseIdMap = lastTrainPoByTypeCodeAndCourseIdAndStudentIdMap.get(trainCount.getStudentId());
            // 获取最新练习信息
            if (CollectionUtil.isNotEmpty(lastTrainPoByTypeCodeAndCourseIdMap)
                    && lastTrainPoByTypeCodeAndCourseIdMap.containsKey(trainCount.getCourseId())) {
                Map<String, TrainPo> lastTrainPoByTypeCodeMap = lastTrainPoByTypeCodeAndCourseIdMap.get(trainCount.getCourseId());
                if (lastTrainPoByTypeCodeMap.containsKey(ApiTrainConst.TypeCode.TEST.getCode())) {
                    TrainPo trainPo = lastTrainPoByTypeCodeMap.get(ApiTrainConst.TypeCode.TEST.getCode());
                    mark = trainPo.getMark();
                    Integer durationSecond = trainPo.getDurationSecond();
                    durationTime = DateUtils.getFormatDate(durationSecond);
                }
            }
        }
        String lastTestInfo = StringUtils.format("{}分，用时{}", mark, durationTime);
        trainCount.setLastTestInfo(lastTestInfo);
    }

    /**
     * 补充培训统计数量信息
     *
     * @param trainCount                                     统计信息
     * @param trainCountByTypeCodeAndCourseIdAndStudentIdMap 培训列表信息
     */
    private void supplyPractiseCount(StudentCourseTrainCount trainCount, Map<Long, Map<Long, Map<String, TrainCountPo>>> trainCountByTypeCodeAndCourseIdAndStudentIdMap) {
        Integer practiceInfoQuestionAmount = 0;
        String practiceInfoSumDurationSecond = DEFAULT_DURATION_TIME;
        if (CollectionUtil.isNotEmpty(trainCountByTypeCodeAndCourseIdAndStudentIdMap)
                && trainCountByTypeCodeAndCourseIdAndStudentIdMap.containsKey(trainCount.getStudentId())) {
            Map<Long, Map<String, TrainCountPo>> trainListByTypeCodeAndCourseIdMap = trainCountByTypeCodeAndCourseIdAndStudentIdMap.get(trainCount.getStudentId());
            if (CollectionUtil.isNotEmpty(trainListByTypeCodeAndCourseIdMap)
                    && trainListByTypeCodeAndCourseIdMap.containsKey(trainCount.getCourseId())) {
                Map<String, TrainCountPo> trainListByTypeCodeMap = trainListByTypeCodeAndCourseIdMap.get(trainCount.getCourseId());
                if (trainListByTypeCodeMap.containsKey(ApiTrainConst.TypeCode.PRACTISE.getCode())) {
                    TrainCountPo practiseTrainCountPo = trainListByTypeCodeMap.get(ApiTrainConst.TypeCode.PRACTISE.getCode());
                    practiceInfoQuestionAmount = practiseTrainCountPo.getAnswerAmount();
                    practiceInfoSumDurationSecond = DateUtils.getFormatDate(practiseTrainCountPo.getDurationSecond());
                    trainCount.setLastPracticeDate(practiseTrainCountPo.getLastSubmitTime());
                }
            }
        }
        String practiseInfo = StringUtils.format("共{}题，{}", practiceInfoQuestionAmount, practiceInfoSumDurationSecond);
        trainCount.setPracticeInfo(practiseInfo);
    }

    /**
     * 关联登录情况
     *
     * @param trainCount              练习情况
     * @param studentLoginCountPoList 学员登录情况
     */
    private void supplyLoginInfo(StudentCourseTrainCount trainCount, Map<Long, Map<Long, StudentLoginTimesCountPo>> studentLoginCountPoList) {
        Integer loginNum = 0;
        Date lastLoginTime = null;
        if (studentLoginCountPoList.containsKey(trainCount.getStudentId())) {
            Map<Long, StudentLoginTimesCountPo> loginTimesByCourseIdMap = studentLoginCountPoList.get(trainCount.getStudentId());
            if (loginTimesByCourseIdMap.containsKey(trainCount.getCourseId())) {
                StudentLoginTimesCountPo studentLoginTimesCountPo = loginTimesByCourseIdMap.get(trainCount.getCourseId());
                loginNum = studentLoginTimesCountPo.getTimes();
                lastLoginTime = studentLoginTimesCountPo.getLastLoginTime();
            }
        }
        trainCount.setLoginNum(loginNum);
        trainCount.setLastLoginTime(lastLoginTime);
    }
}
